package com.juben.svr.demos.web;

import com.itextpdf.commons.utils.JsonUtil;
import com.juben.svr.domain.Conversations;
import com.juben.svr.domain.User;
import com.juben.svr.domain.jb_messages;
import com.juben.svr.mapper.ConversationMapper;
import com.juben.svr.mapper.JubenMessageMapper;
import com.juben.svr.mapper.usermapper;
import com.juben.svr.service.util.CurPool;
import com.juben.svr.service.util.JsonUtils;
import com.juben.svr.service.util.SpringContextUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.*;

@Component
@ServerEndpoint("/websocket/{userId}/{sessionId}")
//此注解相当于设置访问URL
public class WebSocket {

    @Autowired
    private usermapper userMapper;
    @Autowired
    private ConversationMapper conversationMapper; // 会话列表

    @Autowired
    private  JubenMessageMapper JubenMessageMapper; // 消息内容（msg_info)
    private Session session;    //会话
    //连接建立成功回调方法
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "userId")Integer userId,@PathParam(value = "sessionId")String sessionId) {
        //获取当前会话
        System.out.println("建立连接");
        this.session = session;
        //将用户加入会话池
        CurPool.webSockets.put(userId,this);    //添加用户,this 为当前对象,UserId为用户id
        List<Object> list = new ArrayList<>();  //创建一个集合,用于存储用户信息
        list.add(sessionId);
        list.add(session);
        CurPool.sessionPool.put(userId,list);   //将用户信息存入sessionPool;sessionPool是存储会话信息的映射表
        System.out.println("【websocket消息】有新的连接，总数为:"+CurPool.webSockets.size());    //输出当前连接数
    }
    /**
     *
     * */
    @OnClose
    public void onClose() {
        System.out.println("断开连接");
        System.out.println(this.session);
        //断开连接删除用户删除session
        ////从当前会话对象 session 的请求参数中获取 userId，并将其转换为 Integer 类型。
        //getRequestParameterMap() 方法会返回一个包含请求参数的映射，这里获取 userId。
        Integer UserId = Integer.parseInt(this.session.getRequestParameterMap().get("userId").get(0));
        //从会话池 CurPool.sessionPool 中移除与该 userId 关联的会话信息
//        sessionPool 用于保存活跃的会话，以便能在后续的消息处理时查找。
        CurPool.sessionPool.remove(UserId);
        //从 WebSocket 列表 CurPool.webSockets 中移除与该 userId 关联的 WebSocket 对象。
        //webSockets 用于保存当前连接的用户（基于其 userId），以便能向这些用户发送消息。
        CurPool.webSockets.remove(UserId);
        //        检查 userMapper 是否为 null。如果是，则通过 SpringContextUtil 手动获取 UserMapper 的实例。
//        这种方式允许在 WebSocket 中上下文中使用 Spring 管理的 bean。
//        if (userMapper == null){
//            this.userMapper = (UserMapper)SpringContextUtil.getBean("userMapper");  // 手动注入
//        }
        //使用 userMapper 根据 userId 查询用户信息，并将结果存储在 User 对象中。
        //selectByPrimaryKey 是一个常见的方法，用于通过主键查找数据库中的记录。
        if (userMapper == null){
            this.userMapper = (usermapper) SpringContextUtil.getBean("usermapper");  // 手动注入
        }
        User user = userMapper.getUserById(UserId);
        //从当前用户池 CurPool.curUserPool 中移除该用户的名称。这通常用于追踪活跃用户，以便于后续的操作或广播消息。
        CurPool.curUserPool.remove(user.getUname());
        System.out.println("【websocket消息】连接断开，总数为:"+CurPool.webSockets.size());
    }
    /**
     * 处理接收到的消息
     *
     * @param message 客户端发送过来的消息内容
     */
    @OnMessage
    public void onMessage(String message){
        System.out.println("【websocket消息】收到客户端发来的消息:"+message);
        //从当前会话对象 session 中获取请求参数中的 sessionId。这是一个唯一标识符，表示当前会话。
        String sessionId = this.session.getRequestParameterMap().get("sessionId").get(0);
        System.out.println("sessionId:"+sessionId);
//        /检查 sessionId 是否为 null，如果是，则打印错误消息，表示会话 ID 获取失败。不过并不终止方法执行。
        if (sessionId == null){
            System.out.println("sessionId 错误");
        }
        // 在这里无法注入Mapper所以使用这种方式注入Mapper
//        检查 seesionListMapper 是否未初始化（即为 null），如果是，则通过 SpringContextUtil 手动获取对应的 Mapper 实例。主要用于数据库操作。

        if (conversationMapper == null){
            this.conversationMapper = (ConversationMapper) SpringContextUtil.getBean("conversationMapper");
        }

        if (userMapper == null){
            this.userMapper = (usermapper) SpringContextUtil.getBean("usermapper");
        }
        if (JubenMessageMapper == null){
            this.JubenMessageMapper = (JubenMessageMapper) SpringContextUtil.getBean("jubenMessageMapper");
        }

        // 根据会话ID获取会话详情
//        使用 seesionListMapper 查询获得与此 sessionId 关联的会话详情，结果存储在 sessionList 中。
        Conversations sessionList = conversationMapper.getConversationByID(Integer.parseInt(sessionId));
        System.out.println("sessionList:"+sessionList);

        //修改会话列表的最后发送消息的时间
        //获取当前时间并格式化为字符串；用于更新Conversations的last_msg_time字段。
        String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        Conversations Updateconversations = new Conversations();
        Updateconversations.setUser_id(sessionList.getUser_id());
        Updateconversations.setToUserId(sessionList.getToUserId());
        Updateconversations.setLast_message_time(time);
        System.out.println("需要修改的参数："+Updateconversations);
        //进行修改
        conversationMapper.setLastTime(Updateconversations);


        // 根据用户ID获取用户信息
//        根据 sessionList 中的 userId 查询用户信息，并将结果存储在 user 对象中。这个信息后续可能用于消息发送。
        User user = userMapper.getUserById(sessionList.getUser_id());
        // 创建消息对象并设置消息内容
        //创建一个新的 MsgInfo 对象用于保存消息信息。
        jb_messages msgInfo = new jb_messages();
        msgInfo.setMdata(message);  //设置消息内容
        String mdate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        msgInfo.setMdate(mdate);    //设置消息发送时间
        msgInfo.setSenderId(sessionList.getUser_id()); //设置消息发送者ID
        msgInfo.setSenderName(user.getUname()); //设置消息发送者名称
        msgInfo.setRecipientID(sessionList.getToUserId());  //设置消息接收者ID
        msgInfo.setRecipientName(sessionList.getList_name());   //设置消息接收者名称
        msgInfo.setAvatar(user.getHeadlmg()); //设置消息接收头像
        msgInfo.setUn_read_flag(0);
        //消息持久化
        System.out.println("msgInfo" + msgInfo);
        JubenMessageMapper.insert(msgInfo);

        // 判断用户是否存在，不存在就结束
        List<Object> list = CurPool.sessionPool.get(sessionList.getToUserId());
        System.out.println("判断用户是否存在，不存在就结束===list:"+list);
        if (list == null || list.isEmpty()){
            // 用户不存在，更新未读数
            conversationMapper.addUnReadCount(sessionList.getToUserId(), sessionList.getUser_id());
        }else {
            //用户存在判断会话是否存在
            String id = conversationMapper.selectIdByUser(sessionList.getToUserId(), sessionList.getUser_id())+"";  //对方的会话ID
            String o = list.get(0) + "";    //当前会话ID
            if (id.equals(o)){
                //会话存在直接发送消息
                System.out.println("会话存在直接发送消息");
                sendTextMessage(sessionList.getToUserId(), JsonUtils.objectToJson(msgInfo));
            }else {
                //判断会话列表是否存在
                System.out.println("判断会话是否存在：id:"+id);
                if (id == null || "".equals(id) || "null".equals(id)){
                    //不存在就创建会话（新增会话列表）
                    Conversations  tmpSessionList = new Conversations();
                    tmpSessionList.setUser_id(sessionList.getToUserId());
                    tmpSessionList.setToUserId(sessionList.getUser_id());
                    tmpSessionList.setList_name(user.getUname());
                    tmpSessionList.setUn_read_count(1);
//                    conversationMapper.addUnReadCount(sessionList.getToUserId(), sessionList.getUser_id());
                    conversationMapper.insert(tmpSessionList);
                }else {
                    //更新未读消息数
                    conversationMapper.addUnReadCount(sessionList.getToUserId(), sessionList.getUser_id());
                }
                //会话不存在发送列表消息
                List<Conversations> conversations = conversationMapper.selectByUserId(sessionList.getUser_id());
                sendTextMessage(sessionList.getToUserId(), JsonUtils.objectToJson(conversations));
            }
        }
        System.out.println("【websocket消息】收到客户端消息:"+message+"来自用户ID:"+sessionList.getUser_id()+"用户名:"+user.getUname());
    }
    // 此为单点消息 (发送文本)
    public void sendTextMessage(Integer userId, String message) {
        System.out.println("【websocket消息】广播消息, message=" + message);
        Session session = (Session)CurPool.sessionPool.get(userId).get(1);  //
        if (session != null) {
            try {
                session.getBasicRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
